/*
 * TraceCmdMain.c
 *
 *  Created on: 2012/07/11
 *      Author: guanxiaoying
 */

#include "../tracedef.h"
#include "trace_cmd.h"
static struct _OPTION_KEYWORD
{
	PSZ  pszKey;
	U2   u2Id;
}stCmdTrOptionKey[] =
{
		{ "-loop_once",        TROPT_CMDLIST_LOOP_ONCE },
		{ "-loop_twice",       TROPT_CMDLIST_LOOP_TWICE},
		{ "-loop_3_time",      TROPT_CMDLIST_3_TIME },
		{ "-onceloop_checker_on",        TROPT_CMDLIST_ONCELOOP_CHECKER_ON},
		{ "-onceloop_checker_off",        TROPT_CMDLIST_ONCELOOP_CHECKER_OFF},
		{ "-value_recorder_on",        TROPT_CMDLIST_RECORDER_ON},
		{ "-value_recorder_off",        TROPT_CMDLIST_RECORDER_OFF},
		{ "-enter_callee",        TROPT_CMDLIST_ENTER_CALLEE},
		{ "-skip_callee",        TROPT_CMDLIST_SKIP_CALLEE},
		{ NULL, 0 }
};
static struct _EVENT_KEYWORD {
	PSZ  pszKey;
	U4   event;
}stCmdTrEventKey[] =
{

		{ "/event_command_list",        EVENT_CMDLIST_PREV },
		{ "/stop_at_multiInputPath",       EVENT_CONFLUX_STOP},
		{ "/continue_multiInputPath",      EVENT_CONFLUX_CONTINUE },
		{ "/before_enter_function",        EVENT_CMDLIST_ENTRY_PREV},
		{ "/after_enter_function",        EVENT_CMDLIST_ENTRY_POST},
		{ "/before_exit_function",        EVENT_CMDLIST_EXIT_PREV },
		{ "/after_exit_function",        EVENT_CMDLIST_EXIT_POST },
		{ "/push_path",        EVENT_PATH_PUSH},
		{ "/pop_path",        EVENT_PATH_POP},
		{ "/push_loop",        EVENT_LOOP_PUSH},
		{ "/pop_loop",        EVENT_LOOP_POP},
		{ NULL, 0 }
};
static S4 tr_StartCmdList( VOID ){
	AST astMax = LinkCommandList.getMax();
	AST astMin;
	stCmdListMetaAccess.alloc( astMax );
	if( astMax != stCmdListMetaAccess.getMax() ){
		return TRACEEXIT_FATAL;
	}
	astMax = LinkFunction.getMax();
	stTrFunctionAccess.alloc( astMax );
	if( astMax != stTrFunctionAccess.getMax() ){
		return TRACEEXIT_FATAL;
	}
	for( astMin = MIN_ARRAY; astMin <= astMax; astMin++ ){
		/* collect path info */
		stTrFunctionAccess.function.set( astMin, astMin );
		Tr_PathCollectPathTree( astMin );
	}
	astMax = stCmdPathInfoAccess.getMax();
	for( astMin = MIN_ARRAY; astMin <= astMax; astMin++ ){
		/* collect path info */
		stCmdPathInfoAccess.times.set( astMin, 0 );
	}
	return TRACEEXIT_SUCCESS;
}
static S4  tr_FinishCmdList( VOID ){
	stCmdListMetaAccess.clear();
	stTrFunctionAccess.clear();
	stCmdPathInfoAccess.clear();
	stCmdLoopInfoAccess.clear();
	return TRACEEXIT_SUCCESS;
}
S4	Tr_MainAddTuEntry( AST Tu  ){
	AST astEntry;
	TRY;
	stCmdEntryAccess.alloc(1);
	astEntry = stCmdEntryAccess.getMax();
	stCmdEntryAccess.parameter.set( astEntry, Tu );
	stCmdEntryAccess.kind.set( astEntry, ENTRY_TU );
	CATCH(TRACEEXIT_FATAL);
	return TRACEEXIT_SUCCESS;
}

S4	DLL_EXPORT Tr_CmdAddFunctionEntry( PSZ pszName  ){
	AST astMin;
	AST astMax;
	AST astEntry;
	/*debug,12/10/16,S*/
	PSZ name = NULL;
	/*debug,12/10/16,E*/
	BOOL bFound = FALSE;

	if( str_length( pszName ) == 0 ){
		TraceThrowWarning( TR_CMD_ENTRY_WRONG, 0, "", NULL );
		return TRACEEXIT_SUCCESS;
	}
	TRY;
	astMax = LinkFunction.getMax();
	for( astMin = MIN_ARRAY; astMin<=astMax; astMin++  ){
		name = LinkFunction.getName( astMin );
		if( strcmp( name, pszName ) == 0 ){
			stCmdEntryAccess.alloc(1);
			astEntry = stCmdEntryAccess.getMax();
			stCmdEntryAccess.parameter.set( astEntry, astMin );
			stCmdEntryAccess.kind.set( astEntry, ENTRY_FUNC );
			bFound = TRUE;
		}
	}
	/*debug,12/10/16,S*/
	if( !bFound && name != NULL ){
	/*debug,12/10/16,E*/
		TraceThrowWarning( TR_CMD_ENTRY_WRONG, 0, name, NULL );
	}
	CATCH(TRACEEXIT_FATAL);
	return TRACEEXIT_SUCCESS;
}
EXTERNAL_SYMBOL( Tr_CmdAddFunctionEntry );
/*debug,12/10/15,S*/
S4 DLL_EXPORT Tr_CmdCleanEntry(VOID){
/*debug,12/10/15,S*/
	TRY;
	stCmdEntryAccess.clear();
	CATCH(TRACEEXIT_FATAL);
	if (0 != stCmdEntryAccess.getMax() ){
		return TRACEEXIT_FATAL;
	}
	return TRACEEXIT_SUCCESS;
}
EXTERNAL_SYMBOL( Tr_CmdCleanEntry );
VOID DLL_EXPORT Tr_CmdAddOption( PSZ pszOptKey  ){
	S4  i;
	U2 u2OptID = OPTID_NONE;
	if( str_length( pszOptKey ) == 0 ){
		return ;
	}

	for( i = 0; stCmdTrOptionKey[i].pszKey != NULL; i++  )
	{
		if( strcmp( stCmdTrOptionKey[i].pszKey, pszOptKey ) == 0 )
		{
			u2OptID = stCmdTrOptionKey[i].u2Id;
			break;
		}
	}
	switch( u2OptID ){
	case TROPT_CMDLIST_LOOP_ONCE   :
		stCmdTraceOption.ucLoopOption = 1;
		break;
	case TROPT_CMDLIST_LOOP_TWICE  :
		stCmdTraceOption.ucLoopOption = 2;
		break;
	case TROPT_CMDLIST_3_TIME      :
		stCmdTraceOption.ucLoopOption = 3;
		break;
	case TROPT_CMDLIST_ONCELOOP_CHECKER_ON      :
		stCmdTraceOption.ucDetectOnceLoop = TRUE;
		if( stCmdTraceOption.ucLoopOption < 3 ){
			stCmdTraceOption.ucLoopOption++;
		}
		break;
	case TROPT_CMDLIST_ONCELOOP_CHECKER_OFF     :
		stCmdTraceOption.ucDetectOnceLoop = FALSE;
		if( stCmdTraceOption.ucLoopOption >= 3 ){
			stCmdTraceOption.ucLoopOption--;
		}
		break;
	case TROPT_CMDLIST_RECORDER_ON         :
		stCmdTraceOption.ucRecordValue = TRUE;
		break;
	case TROPT_CMDLIST_RECORDER_OFF        :
		stCmdTraceOption.ucRecordValue = FALSE;
		break;
	case TROPT_CMDLIST_ENTER_CALLEE        :
		stCmdTraceOption.ucCallFuncBody = TRUE;
		break;
	case TROPT_CMDLIST_SKIP_CALLEE         :
		stCmdTraceOption.ucCallFuncBody = FALSE;
		break;
	default:
		break;
	}
}
EXTERNAL_SYMBOL( Tr_CmdAddOption );
VOID DLL_EXPORT Tr_CmdAddCallBackEvent( PSZ event  ){
	S4  i;
//	U2 u2OptID = OPTID_NONE;
	if( str_length( event ) == 0 ){
		return ;
	}

	for( i = 0; stCmdTrEventKey[i].pszKey != NULL; i++  )
	{
		if( strcmp( stCmdTrEventKey[i].pszKey, event ) == 0 )
		{
			stCmdTraceOption.ulCmdEvent |= stCmdTrEventKey[i].event;
			break;
		}
	}
}
EXTERNAL_SYMBOL( Tr_CmdAddCallBackEvent );

S4 DLL_EXPORT Tr_CmdTraceAllEntries( S4 (*pfunc)( AST, U4 ), AST (*getCallee)( AST ) ){
	S4 result = TRACEEXIT_SUCCESS;
	AST astMin;
	AST astMax;
	result = tr_StartCmdList();
	if( result != TRACEEXIT_SUCCESS ){
		return result;
	}
	astMin = MIN_ARRAY;
	astMax = stCmdEntryAccess.getMax();
	stCmdTraceOption.pCallBackFunction = pfunc;
	if( getCallee != NULL ){
		stCmdTraceOption.pGetCallee = getCallee;
	}else{
		stCmdTraceOption.pGetCallee = Tr_FunctionGetCallee;
	}
	for( ; astMin <= astMax; astMin++ ){
		if( stCmdEntryAccess.kind.get( astMin ) == ENTRY_FUNC ){
			result = Tr_FunctionTraceAsEntry( stCmdEntryAccess.parameter.get( astMin ));
		}else{
			//
		}
		if( result != TRACEEXIT_SUCCESS ){
			return result;
		}
	}
//	Tr_PrintfAllLog();
	return tr_FinishCmdList();
}
EXTERNAL_SYMBOL( Tr_CmdTraceAllEntries );
